/*
 * Copyright (c) 2008, Xiong Yingfei, the University of Tokyo
 * All rights reserved.
 */
package ac.jp.u_tokyo.SyncLib.dictionaries;

import static ac.jp.u_tokyo.SyncLib.util.Helper.conflict;
import static ac.jp.u_tokyo.SyncLib.util.Helper.merge;
import static ac.jp.u_tokyo.SyncLib.util.Helper.toArrayList;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import ac.jp.u_tokyo.SyncLib.IDSync;
import ac.jp.u_tokyo.SyncLib.Mod;
import ac.jp.u_tokyo.SyncLib.ModTypeUnsupportedException;
import ac.jp.u_tokyo.SyncLib.NullMod;
import ac.jp.u_tokyo.SyncLib.PrimMod;
import ac.jp.u_tokyo.SyncLib.StatelessSync;
import ac.jp.u_tokyo.SyncLib.Sync;
import ac.jp.u_tokyo.SyncLib.SynchronizationFailedException;
import ac.jp.u_tokyo.SyncLib.util.Helper;

public class StaticGet<K> extends StatelessSync
{
	boolean _dictOverVal;
	K _key;
//	ForMap _initialMap;

	public StaticGet(K key, boolean dictOverVal/*, ForMap initialMap*/) {
		_dictOverVal = dictOverVal;
		_key = key;
//		_initialMap = initialMap;
	}

	public int getParaCount()
	{
		return 2;
	}
	
	
	@Override
	public boolean isModConcerned(int index, Mod mod) throws ModTypeUnsupportedException
	{
		if (index == 0) {
			if (mod instanceof NullMod) return false;
			if (false == mod instanceof DictMod) throw new ModTypeUnsupportedException();
			DictMod dmod = (DictMod) mod;
			return !(dmod.getMod(_key) instanceof NullMod);
		}
		return super.isModConcerned(index, mod);
	}




	private static final DictMod NULLDICTMOD = new DictMod(new HashMap(0));

	public boolean isDictOverVal()
	{
		return _dictOverVal;
	}

	public void setDictOverVal(boolean dictOverVal)
	{
		_dictOverVal = dictOverVal;
	}

//	public Object[] getInitialValues()
//	{
//		return new Object[] {_initialMap, _initialMap.get(_key)};
//	}

	public Mod[] resynchronize(Object[] values, Mod[] modifications)
			throws SynchronizationFailedException
	{
		assert modifications[0] != null;
		assert modifications[1] != null;

		if (false == modifications[0] instanceof NullMod && false == modifications[0] instanceof DictMod)
			throw new SynchronizationFailedException();

		DictMod<K, Object> dictMod1; 
		if (modifications[0] instanceof NullMod) dictMod1 = NULLDICTMOD;
		else dictMod1 = ((DictMod<K, Object>)modifications[0]);

		Mod mod1 = dictMod1.getMod(_key);
		Mod mod2 = modifications[1];

		if (conflict(mod1, mod2)) throw new SynchronizationFailedException();

		Map<K, Object> dict = (Map<K, Object>)values[0];
		if (dict == null) dict = new HashMap<K, Object>();
		Object v = values[1];
		Mod vresult = IDSync.mergeWithValue(mod1, mod2, dict.get(_key), v, _dictOverVal);
		Mod dresult = DictMod.replace(dictMod1, _key, vresult);
		if (dresult.equals(NULLDICTMOD) && modifications[0] instanceof NullMod && values[0] != null) 
			dresult = NullMod.INSTANCE;
		return new Mod[] {dresult, vresult};
	}

	public Mod[] synchronize(Mod[] modifications)
			throws SynchronizationFailedException
	{
		assert modifications[0] != null;
		assert modifications[1] != null;
		
		if (false == modifications[0] instanceof NullMod && false == modifications[0] instanceof DictMod)
			throw new SynchronizationFailedException();
		
		DictMod<K, Object> dictMod1; 
		if (modifications[0] instanceof NullMod) dictMod1 = NULLDICTMOD;
		else dictMod1 = ((DictMod<K, Object>)modifications[0]);
		
		Mod mod1 = dictMod1.getMod(_key);
		Mod mod2 = modifications[1];

		if (conflict(mod1, mod2)) throw new SynchronizationFailedException();

		Mod vresult = merge(mod1, mod2);
		Mod dresult = DictMod.replace(dictMod1, _key, vresult);
		if (dresult.equals(NULLDICTMOD) && (modifications[0] instanceof NullMod)) 
				dresult = NullMod.INSTANCE;
		return new Mod[] {dresult, vresult};
		
	}

	@Override
	public String toString()
	{
		return "StaticGet[" + _key + "]";
	}

	
}
